#include "Avalon/Serialization/DataShuttle.hpp"
#include "Avalon/IO/Buffer.hpp"
#include <boost/tuple/tuple.hpp>

using namespace Avalon;
using namespace Avalon::IO;
using namespace Avalon::Serialization;
using namespace boost;
using namespace std;

namespace {
  map<const type_info*, tuple<const char*, unsigned int> >&
      PolymorphicVersions() {
    static map<const type_info*, tuple<const char*, unsigned int> >
      polymorphicVersions;
    return polymorphicVersions;
  }
}

void DataShuttle::Shuttle(const char* name, const bool& value) {
  Shuttle(name, const_cast<bool&>(value));
}

void DataShuttle::Shuttle(const char* name, const char& value) {
  Shuttle(name, const_cast<char&>(value));
}

void DataShuttle::Shuttle(const char* name, const unsigned char& value) {
  Shuttle(name, const_cast<unsigned char&>(value));
}

void DataShuttle::Shuttle(const char* name, const short& value) {
  Shuttle(name, const_cast<short&>(value));
}

void DataShuttle::Shuttle(const char* name, const unsigned short& value) {
  Shuttle(name, const_cast<unsigned short&>(value));
}

void DataShuttle::Shuttle(const char* name, const int& value) {
  Shuttle(name, const_cast<int&>(value));
}

void DataShuttle::Shuttle(const char* name, const unsigned int& value) {
  Shuttle(name, const_cast<unsigned int&>(value));
}

void DataShuttle::Shuttle(const char* name, const long& value) {
  Shuttle(name, const_cast<long&>(value));
}

void DataShuttle::Shuttle(const char* name, const unsigned long& value) {
  Shuttle(name, const_cast<unsigned long&>(value));
}

void DataShuttle::Shuttle(const char* name, const long long& value) {
  Shuttle(name, const_cast<long long&>(value));
}

void DataShuttle::Shuttle(const char* name, const unsigned long long& value) {
  Shuttle(name, const_cast<unsigned long long&>(value));
}

void DataShuttle::Shuttle(const char* name, const float& value) {
  Shuttle(name, const_cast<float&>(value));
}

void DataShuttle::Shuttle(const char* name, const double& value) {
  Shuttle(name, const_cast<double&>(value));
}

void DataShuttle::Shuttle(const char* name, const string& value) {
  Shuttle(name, const_cast<string&>(value));
}

void DataShuttle::Shuttle(const char* name, const Buffer& data) {
  Shuttle(name, const_cast<Buffer&>(data));
}

void DataShuttle::StartStructure(const char* name) {}

void DataShuttle::EndStructure() {}

void DataShuttle::StartSequence(const char* name) {}

void DataShuttle::EndSequence() {}

map<string, DataShuttle::ConstructorType>&
    DataShuttle::GetTypeNameToConstructor() {
  static map<string, DataShuttle::ConstructorType> typeNameToConstructor;
  return typeNameToConstructor;
}

map<string, DataShuttle::SharedConstructorType>&
    DataShuttle::GetTypeNameToSharedConstructor() {
  static map<string, DataShuttle::SharedConstructorType> typeNameToConstructor;
  return typeNameToConstructor;
}

unsigned int DataShuttle::GetPolymorphicVersion(const type_info& type) {
  map<const type_info*, tuple<const char*, unsigned int> >::const_iterator
    versionIterator = PolymorphicVersions().find(&type);
  if(versionIterator == PolymorphicVersions().end()) {
    return 0;
  }
  return versionIterator->second.get<1>();
}

const char* DataShuttle::GetName(const type_info& type) {
  map<const type_info*, tuple<const char*, unsigned int> >::const_iterator
    versionIterator = PolymorphicVersions().find(&type);
  if(versionIterator == PolymorphicVersions().end()) {
    return NULL;
  }
  return versionIterator->second.get<0>();
}

void DataShuttle::SetPolymorphicVersion(const type_info& type, const char* name,
    unsigned int version) {
  PolymorphicVersions()[&type] = make_tuple(name, version);
}

DataShuttle::DataShuttle()
    : m_versioningEnabled(true) {}

DataShuttle::~DataShuttle() {}

void DataShuttle::DisableVersioning() {
  m_versioningEnabled = false;
}

void DataShuttle::Shuttle(const char* name, unsigned char& value) {
  Shuttle(name, reinterpret_cast<char&>(value));
}

void DataShuttle::Shuttle(const char* name, unsigned short& value) {
  Shuttle(name, reinterpret_cast<short&>(value));
}

void DataShuttle::Shuttle(const char* name, unsigned int& value) {
  Shuttle(name, reinterpret_cast<int&>(value));
}

void DataShuttle::Shuttle(const char* name, unsigned long& value) {
  Shuttle(name, reinterpret_cast<long&>(value));
}

void DataShuttle::Shuttle(const char* name, unsigned long long& value) {
  Shuttle(name, reinterpret_cast<long long&>(value));
}

DataShuttle::ConstructorType DataShuttle::FindConstructor() {
  return ConstructorType();
}

DataShuttle::SharedConstructorType DataShuttle::FindSharedConstructor() {
  return SharedConstructorType();
}

void DataShuttle::SendNull() {}

void DataShuttle::SendPointer(const type_info& typeInfo) {}

void DataShuttle::SendSharedPointer(const type_info& typeInfo) {}
